﻿using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using System.Web;

namespace NahidaProject4CSharp.Generic
{
	/// <summary>
	/// HTTP 请求方法枚举
	/// </summary>
	public enum HttpMethodType
	{
		GET,
		POST,
		PUT,
		DELETE,
		PATCH,
		HEAD,
		OPTIONS
	}

	/// <summary>
	/// HTTP 响应结果类
	/// </summary>
	public class HTTPResponse
	{
		public int StatusCode { get; set; }
		public string Content { get; set; }
		public Dictionary<string, string> Headers { get; set; }
		public bool IsSuccess { get; set; }
		public string ErrorMessage { get; set; }

		public HTTPResponse()
		{
			Headers = new Dictionary<string, string>();
		}
	}

	/// <summary>
	/// 功能完善的 HTTP 请求类
	/// </summary>
	public class HTTPRequestClient : IDisposable
	{
		private HttpClient _httpClient;
		private HttpClientHandler _httpClientHandler;
		private bool _disposed = false;

		/// <summary>
		/// 构造函数
		/// </summary>
		public HTTPRequestClient()
		{
			_httpClientHandler = new HttpClientHandler();
			_httpClient = new HttpClient(_httpClientHandler);
			SetDefaultHeaders();
		}

		/// <summary>
		/// 构造函数（带基础URL）
		/// </summary>
		/// <param name="baseUrl">基础URL</param>
		public HTTPRequestClient(string baseUrl) : this()
		{
			if (!string.IsNullOrEmpty(baseUrl))
			{
				_httpClient.BaseAddress = new Uri(baseUrl);
			}
		}

		/// <summary>
		/// 设置默认请求头
		/// </summary>
		private void SetDefaultHeaders()
		{
			_httpClient.DefaultRequestHeaders.Add("User-Agent", "HttpRequestClient/1.0");
		}

		#region 配置方法

		/// <summary>
		/// 设置超时时间
		/// </summary>
		/// <param name="timeout">超时时间（毫秒）</param>
		public void SetTimeout(int timeout)
		{
			_httpClient.Timeout = TimeSpan.FromMilliseconds(timeout);
		}

		/// <summary>
		/// 设置超时时间
		/// </summary>
		/// <param name="timeout">超时时间</param>
		public void SetTimeout(TimeSpan timeout)
		{
			_httpClient.Timeout = timeout;
		}

		/// <summary>
		/// 设置是否使用默认凭据
		/// </summary>
		/// <param name="useDefaultCredentials">是否使用默认凭据</param>
		public void SetUseDefaultCredentials(bool useDefaultCredentials)
		{
			_httpClientHandler.UseDefaultCredentials = useDefaultCredentials;
		}

		/// <summary>
		/// 设置是否允许自动重定向
		/// </summary>
		/// <param name="allowAutoRedirect">是否允许自动重定向</param>
		public void SetAllowAutoRedirect(bool allowAutoRedirect)
		{
			_httpClientHandler.AllowAutoRedirect = allowAutoRedirect;
		}

		/// <summary>
		/// 设置最大自动重定向次数
		/// </summary>
		/// <param name="maxRedirects">最大重定向次数</param>
		public void SetMaxAutomaticRedirections(int maxRedirects)
		{
			_httpClientHandler.MaxAutomaticRedirections = maxRedirects;
		}

		/// <summary>
		/// 设置代理
		/// </summary>
		/// <param name="proxy">代理服务器</param>
		public void SetProxy(IWebProxy proxy)
		{
			_httpClientHandler.Proxy = proxy;
		}

		/// <summary>
		/// 设置Cookie容器
		/// </summary>
		/// <param name="cookieContainer">Cookie容器</param>
		public void SetCookieContainer(CookieContainer cookieContainer)
		{
			_httpClientHandler.CookieContainer = cookieContainer;
		}

		/// <summary>
		/// 添加默认请求头
		/// </summary>
		/// <param name="name">头名称</param>
		/// <param name="value">头值</param>
		public void AddDefaultHeader(string name, string value)
		{
			_httpClient.DefaultRequestHeaders.Add(name, value);
		}

		/// <summary>
		/// 清除默认请求头
		/// </summary>
		/// <param name="name">头名称</param>
		public void RemoveDefaultHeader(string name)
		{
			_httpClient.DefaultRequestHeaders.Remove(name);
		}

		/// <summary>
		/// 清除所有默认请求头
		/// </summary>
		public void ClearDefaultHeaders()
		{
			_httpClient.DefaultRequestHeaders.Clear();
		}

		#endregion

		#region GET 请求

		/// <summary>
		/// 发送 GET 请求
		/// </summary>
		/// <param name="url">请求URL</param>
		/// <returns>HTTP响应</returns>
		public async Task<HTTPResponse> GetAsync(string url)
		{
			return await SendAsync(HttpMethodType.GET, url, null, null);
		}

		/// <summary>
		/// 发送 GET 请求（带查询参数）
		/// </summary>
		/// <param name="url">请求URL</param>
		/// <param name="parameters">查询参数</param>
		/// <returns>HTTP响应</returns>
		public async Task<HTTPResponse> GetAsync(string url, Dictionary<string, string> parameters)
		{
			string fullUrl = BuildUrlWithParameters(url, parameters);
			return await SendAsync(HttpMethodType.GET, fullUrl, null, null);
		}

		/// <summary>
		/// 发送 GET 请求（带请求头）
		/// </summary>
		/// <param name="url">请求URL</param>
		/// <param name="headers">请求头</param>
		/// <returns>HTTP响应</returns>
		public async Task<HTTPResponse> GetAsyncWithRequestHeader(string url, Dictionary<string, string> headers)
		{
			return await SendAsync(HttpMethodType.GET, url, null, headers);
		}

		/// <summary>
		/// 发送 GET 请求（带查询参数和请求头）
		/// </summary>
		/// <param name="url">请求URL</param>
		/// <param name="parameters">查询参数</param>
		/// <param name="headers">请求头</param>
		/// <returns>HTTP响应</returns>
		public async Task<HTTPResponse> GetAsync(string url, Dictionary<string, string> parameters, Dictionary<string, string> headers)
		{
			string fullUrl = BuildUrlWithParameters(url, parameters);
			return await SendAsync(HttpMethodType.GET, fullUrl, null, headers);
		}

		#endregion

		#region POST 请求

		/// <summary>
		/// 发送 POST 请求（JSON数据）
		/// </summary>
		/// <param name="url">请求URL</param>
		/// <param name="jsonData">JSON数据</param>
		/// <returns>HTTP响应</returns>
		public async Task<HTTPResponse> PostJsonAsync(string url, string jsonData)
		{
			return await SendAsync(HttpMethodType.POST, url, jsonData, null, "application/json");
		}

		/// <summary>
		/// 发送 POST 请求（JSON数据和请求头）
		/// </summary>
		/// <param name="url">请求URL</param>
		/// <param name="jsonData">JSON数据</param>
		/// <param name="headers">请求头</param>
		/// <returns>HTTP响应</returns>
		public async Task<HTTPResponse> PostJsonAsync(string url, string jsonData, Dictionary<string, string> headers)
		{
			return await SendAsync(HttpMethodType.POST, url, jsonData, headers, "application/json");
		}

		/// <summary>
		/// 发送 POST 请求（表单数据）
		/// </summary>
		/// <param name="url">请求URL</param>
		/// <param name="formData">表单数据</param>
		/// <returns>HTTP响应</returns>
		public async Task<HTTPResponse> PostFormAsync(string url, Dictionary<string, string> formData)
		{
			return await SendAsync(HttpMethodType.POST, url, formData, null);
		}

		/// <summary>
		/// 发送 POST 请求（表单数据和请求头）
		/// </summary>
		/// <param name="url">请求URL</param>
		/// <param name="formData">表单数据</param>
		/// <param name="headers">请求头</param>
		/// <returns>HTTP响应</returns>
		public async Task<HTTPResponse> PostFormAsync(string url, Dictionary<string, string> formData, Dictionary<string, string> headers)
		{
			return await SendAsync(HttpMethodType.POST, url, formData, headers);
		}

		/// <summary>
		/// 发送 POST 请求（原始数据）
		/// </summary>
		/// <param name="url">请求URL</param>
		/// <param name="data">原始数据</param>
		/// <param name="contentType">内容类型</param>
		/// <returns>HTTP响应</returns>
		public async Task<HTTPResponse> PostAsync(string url, string data, string contentType = "text/plain")
		{
			return await SendAsync(HttpMethodType.POST, url, data, null, contentType);
		}

		/// <summary>
		/// 发送 POST 请求（原始数据和请求头）
		/// </summary>
		/// <param name="url">请求URL</param>
		/// <param name="data">原始数据</param>
		/// <param name="headers">请求头</param>
		/// <param name="contentType">内容类型</param>
		/// <returns>HTTP响应</returns>
		public async Task<HTTPResponse> PostAsync(string url, string data, Dictionary<string, string> headers, string contentType = "text/plain")
		{
			return await SendAsync(HttpMethodType.POST, url, data, headers, contentType);
		}

		#endregion

		#region PUT 请求

		/// <summary>
		/// 发送 PUT 请求（JSON数据）
		/// </summary>
		/// <param name="url">请求URL</param>
		/// <param name="jsonData">JSON数据</param>
		/// <returns>HTTP响应</returns>
		public async Task<HTTPResponse> PutJsonAsync(string url, string jsonData)
		{
			return await SendAsync(HttpMethodType.PUT, url, jsonData, null, "application/json");
		}

		/// <summary>
		/// 发送 PUT 请求（表单数据）
		/// </summary>
		/// <param name="url">请求URL</param>
		/// <param name="formData">表单数据</param>
		/// <returns>HTTP响应</returns>
		public async Task<HTTPResponse> PutFormAsync(string url, Dictionary<string, string> formData)
		{
			return await SendAsync(HttpMethodType.PUT, url, formData, null);
		}

		/// <summary>
		/// 发送 PUT 请求（原始数据）
		/// </summary>
		/// <param name="url">请求URL</param>
		/// <param name="data">原始数据</param>
		/// <param name="contentType">内容类型</param>
		/// <returns>HTTP响应</returns>
		public async Task<HTTPResponse> PutAsync(string url, string data, string contentType = "text/plain")
		{
			return await SendAsync(HttpMethodType.PUT, url, data, null, contentType);
		}

		#endregion

		#region DELETE 请求

		/// <summary>
		/// 发送 DELETE 请求
		/// </summary>
		/// <param name="url">请求URL</param>
		/// <returns>HTTP响应</returns>
		public async Task<HTTPResponse> DeleteAsync(string url)
		{
			return await SendAsync(HttpMethodType.DELETE, url, null, null);
		}

		/// <summary>
		/// 发送 DELETE 请求（带请求头）
		/// </summary>
		/// <param name="url">请求URL</param>
		/// <param name="headers">请求头</param>
		/// <returns>HTTP响应</returns>
		public async Task<HTTPResponse> DeleteAsync(string url, Dictionary<string, string> headers)
		{
			return await SendAsync(HttpMethodType.DELETE, url, null, headers);
		}

		#endregion

		#region PATCH 请求

		/// <summary>
		/// 发送 PATCH 请求（JSON数据）
		/// </summary>
		/// <param name="url">请求URL</param>
		/// <param name="jsonData">JSON数据</param>
		/// <returns>HTTP响应</returns>
		public async Task<HTTPResponse> PatchJsonAsync(string url, string jsonData)
		{
			return await SendAsync(HttpMethodType.PATCH, url, jsonData, null, "application/json");
		}

		/// <summary>
		/// 发送 PATCH 请求（原始数据）
		/// </summary>
		/// <param name="url">请求URL</param>
		/// <param name="data">原始数据</param>
		/// <param name="contentType">内容类型</param>
		/// <returns>HTTP响应</returns>
		public async Task<HTTPResponse> PatchAsync(string url, string data, string contentType = "text/plain")
		{
			return await SendAsync(HttpMethodType.PATCH, url, data, null, contentType);
		}

		#endregion

		#region 通用请求方法

		/// <summary>
		/// 发送 HTTP 请求
		/// </summary>
		/// <param name="method">HTTP方法</param>
		/// <param name="url">请求URL</param>
		/// <param name="data">请求数据</param>
		/// <param name="headers">请求头</param>
		/// <param name="contentType">内容类型</param>
		/// <returns>HTTP响应</returns>
		public async Task<HTTPResponse> SendAsync(HttpMethodType method, string url, object data, Dictionary<string, string> headers, string contentType = null)
		{
			if (_disposed)
				throw new ObjectDisposedException(nameof(HTTPRequestClient));

			try
			{
				using (var request = CreateHttpRequest(method, url, data, headers, contentType))
				{
					using (var response = await _httpClient.SendAsync(request))
					{
						return await ProcessResponseAsync(response);
					}
				}
			}
			catch (Exception ex)
			{
				return new HTTPResponse
				{
					IsSuccess = false,
					ErrorMessage = ex.Message
				};
			}
		}

		/// <summary>
		/// 创建 HTTP 请求消息
		/// </summary>
		private HttpRequestMessage CreateHttpRequest(HttpMethodType method, string url, object data, Dictionary<string, string> headers, string contentType)
		{
			var request = new HttpRequestMessage(new HttpMethod(method.ToString()), url);

			// 添加请求头
			if (headers != null)
			{
				foreach (var header in headers)
				{
					request.Headers.Add(header.Key, header.Value);
				}
			}

			// 添加请求内容
			if (data != null)
			{
				if (data is string stringData)
				{
					request.Content = new StringContent(stringData, Encoding.UTF8, contentType ?? "text/plain");
				}
				else if (data is Dictionary<string, string> formData)
				{
					request.Content = new FormUrlEncodedContent(formData);
				}
			}

			return request;
		}

		/// <summary>
		/// 处理 HTTP 响应
		/// </summary>
		private async Task<HTTPResponse> ProcessResponseAsync(HttpResponseMessage response)
		{
			var result = new HTTPResponse
			{
				StatusCode = (int)response.StatusCode,
				IsSuccess = response.IsSuccessStatusCode,
				Headers = new Dictionary<string, string>()
			};

			// 读取响应头
			foreach (var header in response.Headers)
			{
				result.Headers[header.Key] = string.Join(",", header.Value);
			}

			// 读取响应内容
			if (response.Content != null)
			{
				result.Content = await response.Content.ReadAsStringAsync();
			}

			return result;
		}

		#endregion

		#region 辅助方法

		/// <summary>
		/// 构建带查询参数的URL
		/// </summary>
		private string BuildUrlWithParameters(string url, Dictionary<string, string> parameters)
		{
			if (parameters == null || parameters.Count == 0)
				return url;

			var uriBuilder = new UriBuilder(url);
			var query = System.Web.HttpUtility.ParseQueryString(uriBuilder.Query);

			foreach (var param in parameters)
			{
				query[param.Key] = param.Value;
			}

			uriBuilder.Query = query.ToString();
			return uriBuilder.ToString();
		}

		#endregion

		#region IDisposable 实现

		/// <summary>
		/// 释放资源
		/// </summary>
		public void Dispose()
		{
			Dispose(true);
			GC.SuppressFinalize(this);
		}

		/// <summary>
		/// 释放资源
		/// </summary>
		protected virtual void Dispose(bool disposing)
		{
			if (!_disposed)
			{
				if (disposing)
				{
					_httpClient?.Dispose();
					_httpClientHandler?.Dispose();
				}
				_disposed = true;
			}
		}

		#endregion
	}
}
